More Programming Information
Back to Win95 ASM Page
Program startup
When a Win95 program starts, the segment registers are set up this way:
CS = code selector
DS = ES = SS = data selector
FS = data selector to TIB (thread information block) for the first
thread
GS = 0, the null selector
CS maps to the same linear address as DS, ES, and SS.
FS maps to a TIB which is embedded in a data block
known as the TDB (thread data base). The TIB contains the thread-specific
exception handling chain and pointer to the TLS (thread local storage.)
The thread local storage is not the same as C local storage.
ESP is set by Win95 to a high address, not necessarily
at the 2G mark.
DF (descending/direction flag) is cleared, so string
ops will cause an increment (ascending mode.)
If you've ever programmed a protected mode switcher, you'll know how
CS can have a different "segment" value and still be able to address the
same memory area with the same offsets.
For ASM programmers who aren't familiar with protected
mode, the "segment" is no longer a segment (paragraph) value, it's a selector.
A selector is a reference to a descriptor, where information about the
"segment" (which can be any size) is stored.
Other startup values
Previous instance handle:
There is no previous instance handle because instance
handles cannot be used to access data from another process (application
instance). The WinMain parameter is always 0 (NULL.) Other techniques exist
for ensuring only one instance (running copy) of an application.
Instance/module handle of EXE:
push large 0 ; NULL string pointer
call GetModuleHandle ; EAX = hInstance of EXE
Command line arguments:
call GetCommandLine ; EAX = pointer to full command line
[Environment variables:]
Standard I/O, nCmdShow:
STARTUPINFO struc
startSize dd ? ; cb, size of STARTUPINFO
dd ? ; lpReserved
startDesktop dd ? ; lpDesktop, (string) name of desktop
; *** Start of console window info
startTitle dd ? ; lpTitle, (string) title/caption
startX dd ? ; dwX, upper left corner
startY dd ? ; dwY, upper left corner
startXSize dd ? ; dwXSize, width
startYSize dd ? ; dwYSize, height
startXChars dd ? ; dwXCountChars, console width
startYChars dd ? ; dwYCountChars, console height
startFillAttr dd ? ; dwFillAttribute, console window attributes
; *** End of console window info
startFlags dd ? ; dwFlags, option flags, used by CreateProcess
startShowWnd dw ? ; wShowWindow, used in first call to ShowWindow
dw ? ; cbReserved2
dd ? ; lpReserved2
startStdin dd ? ; hStdInput, standard input handle
startStdout dd ? ; hStdOutput, standard output handle
startStderr dd ? ; hStdError, standard error output handle
STARTUPINFO ends
push offset <startupinfo>
call GetStartupInfo ; void function
Creating an import library from an arbitrary
DLL
With the Borland linker, use IMPDEF to create a .DEF file from the DLL.
Then use IMPLIB to create the import library from the .DEF file.
With the Microsoft linker, use DUMPBIN /EXPORTS to get a list of entry
points and their "ordinals". Redirect the output into a .DEF file. Change
each line with an entry point name to:
entryname
Eliminate all other lines. Then add to the beginning of the file:
LIBRARY dllbasename
EXPORTS
Then use LIB /DEF to generate the .LIB file from the editted .DEF file.
LIB will prepend an underscore, "_", to each entry name. Due to the lack
of argument information, LIB will not add any other characters to the link
name.
Deadlock theory
Deadlock, or the deadly embrace, is a condition
where processes are waiting forever to acquire resources
that can't be released. For the purposes of deadlock theory, a Win32 thread
can be treated as a process, and a resource is defined as any allocatable
item.
For reasoning about deadlock due to window messaging,
it's more fruitful to treat each window as a process, and each thread as
a resource that can cause deadlock.
There are four necessary and sufficient conditions
for creating deadlocks.
Necessary means that all conditions must exist
for deadlock to occur.
Sufficient means that when all conditions exist, deadlock
will occur.
According to Tanenbaum [referring to an article by Coffman, Elphick
& Shoshani], they are:
-
Mutual exclusion condition. Each resource is either currently assigned
to exactly one process or is available.
-
Hold and wait condition. Processes currently holding resources granted
earlier can request new resources.
-
No preemption condition. Resources previously granted cannot be
forcibly taken away from a process. They must be explicitly released by
the process holding them.
-
Circular wait condition. There must be a circular chain of two or
more processes, each of which is waiting for a resource held by the next
member of the chain.
Brinch Hansen's restatement [of Coffman et al.] may be more revealing:
-
Mutual exclusion: A resource can only be acquired by one process
at a time.
-
Nonpreemptive scheduling: A resource can only be released by the
process which has acquired it.
-
Partial allocation: A process can acquire its resources piecemeal.
-
Circular waiting: The previous conditions permit concurrent processes
to acquire part of their resources and enter a state in which they wait
indefinitely to acquire each other's resources.
Title (caption) bar and Taskbar button anomalies
The standard Win95 title bar (requested either by default or with WS_CAPTION)
isn't nearly as customizable as the old Win3.1 title bar (NT or 16-bit).
If you want the title bar to behave better, you'll probably have to draw
your own.
When you disable a title bar button, it doesn't
necessarily disappear. The minimize and maximize buttons disappear as a
pair. If you disable one and enable the other, both will show and the disabled
button is grayed. The close (X) button can be disabled (grayed) with CS_NOCLOSE,
but doesn't appear to be removable.
Enabling the minimize button will create a Taskbar
button, but enabling the maximize button won't.
The close button cannot be enabled unless the system
menu is also enabled.
There is some curious behavior when no system menu
and no size buttons are specified. When a shortcut is used to start with
maximized windows, you get a Taskbar button. When the shortcut is used
to start with minimized windows, you get a "button" that doesn't sit in
the Taskbar.
Documented Win32 functions that don't exist
There are a few official API functions that are converted by C macros to
equivalent functions with extra arguments. The extra arguments are 0 or
NULL.
-
CreateWindow, use CreateWindowEx
-
DialogBox, use DialogBoxParam
-
DialogBoxIndirect, use DialogBoxIndirectParam
Obsolete Win16 functions
There are a number of Win16 API functions that either no longer exist in
Win32, or exist solely for compatibility with Win16 programming in C.
-
No longer existing
-
GetModuleUsage, main usage was to wait for other apps to end.
For this purpose, use CreateProcess, OpenProcess, and GetExitCode or
WaitForSingleObject.
-
MoveTo, use MoveToEx